package net.organizer.dao;

import java.util.logging.Logger;

import javax.persistence.Id;
import javax.persistence.PostLoad;
import javax.persistence.PrePersist;
import javax.persistence.Transient;

import org.json.JSONException;
import org.json.JSONObject;

import com.google.appengine.api.datastore.Entity;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.annotation.Parent;

public class OrgPerson {
	private static final Logger logger = Logger.getLogger(OrgPerson.class.getName());
	
	public static Key<OrgPerson> getKey(Domain domain, Long id){
		return new Key<OrgPerson>(domain.getKey(), OrgPerson.class, id);
	}
	@Transient protected Domain domain;
	@Parent protected Key<Domain> domainKey;
	@Id protected Long   id;
	@Transient protected Org org;
	@Transient protected Person person;
	
	protected Long orgId;
	protected Long personId;

	public OrgPerson() {
		super();
	}
	
	public OrgPerson(Org org, Person person, Domain domain) {
		super();
		this.domainKey = domain.getKey();
		this.org = org;
		this.person = person;
		this.orgId = org.getId();
		this.personId = person.getId();
		this.domainKey = domain.getKey();
		this.domain = domain;
	}

	public OrgPerson(Long orgId, Long personId, Domain domain) {
		super();
		this.domainKey = domain.getKey();
		this.orgId = orgId;
		this.personId = personId;
		this.domainKey = domain.getKey();
		this.domain = domain;
	}
	public Domain getDomain() {
		return domain;
	}

	public Key<Domain> getDomainKey() {
		return domainKey;
	}

	public Long getId() {
		return id;
	}

	/**
	 * returns key with domain parent entity reference
	 * @return
	 */
	public Key<OrgPerson> getKey(){
		if(this.domainKey==null){
			throw new UnsupportedOperationException(String.format("attempt to getKey with null instance domain... org: %s", this));
		}
		return new Key<OrgPerson>(domainKey, OrgPerson.class, this.getId());
	}

	public Org getOrg() {
		return org;
	}
	public Person getPerson() {
		return person;
	}
	@PostLoad void postLoad(Objectify ofy, Entity entity){
		//logger.fine(String.format("postLoad... entity: %s", entity));
		this.verifyRequiredFields();
	}
	@PrePersist void prePersist(Objectify ofy, Entity entity){
		//logger.fine(String.format("prePersist... entity: %s", entity));
		this.verifyRequiredFields();
	}
	public void setDomain(Domain domain) {
		this.domain = domain;
	}
	public void setDomainKey(Domain domain) {
		this.domainKey = domain.getKey();
	}
	public void setDomainKey(Key<Domain> domainKey) {
		this.domainKey = domainKey;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public void setOrg(Org org) {
		this.org = org;
		this.orgId = org.getId();
	}
	public void setOrgId(Long orgId) {
		this.orgId = orgId;
	}
	public void setPerson(Person person) {
		this.person = person;
		this.personId = person.getId();
	}
	public void setPersonId(Long personId) {
		this.personId = personId;
	}
	public JSONObject toJSONObject() {
		  JSONObject result = new JSONObject();
		  try {
			result.put("id", this.getId());
			result.put("orgId", this.getOrgId());
			result.put("personId", this.getPersonId());
			
			if(this.getOrg()!=null){
				result.put("org", this.getOrg().toJSONObject());
			}
			if(this.getPerson()!=null){
				result.put("person", this.getPerson().toJSONObject());
			}
		} catch (JSONException e) {
			throw new RuntimeException(e);
		}
		return result;
	}
	public Long getOrgId() {
		return orgId;
	}

	public Long getPersonId() {
		return personId;
	}

	@Override
	public String toString() {
		return "Org [orgId=" + orgId +  ", domain=" + domain
				+ ", domainKey=" + domainKey + ", id=" + id
				+ ", personId= " + personId
				+  "]";
	}
	protected void verifyRequiredFields(){
		//logger.fine(String.format("verifyRequired...%s", this));
		if(this.getDomainKey()==null){
			throw new RuntimeException(String.format("missing required field domainKey...%s", this));
		}
		if(this.getOrgId()==null){
			throw new RuntimeException(String.format("missing required field orgId...%s", this));
		}
		if(this.getPersonId()==null){
			throw new RuntimeException(String.format("missing required field personId...%s", this));
		}
	}
}
